#include <wx/wx.h>
#include <wx/dialog.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/clipbrd.h>

#include "UUIDDialog.h"

#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

UUIDDialog::UUIDDialog( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style )
 : wxDialog( parent, id, title, pos, size, style )
{
	this->SetSizeHints( wxDefaultSize, wxDefaultSize );

	wxBoxSizer* boxSizerAll = new wxBoxSizer( wxVERTICAL );

	wxBoxSizer* verticalSizer = new wxBoxSizer( wxVERTICAL );

	wxBoxSizer* horizontalSizer2;
	horizontalSizer2 = new wxBoxSizer( wxHORIZONTAL );

	m_FormattingLabel = new wxStaticText( this, wxID_ANY, wxT("Format"), wxDefaultPosition, wxDefaultSize, 0 );
	m_FormattingLabel->Wrap( -1 );
	horizontalSizer2->Add( m_FormattingLabel, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 8 );

	wxString m_FormattingChoiceChoices[] =
	{
		wxT("Plain"),
		wxT("Hyphenated"),
		wxT("Hyphenated, enclosed in braces"),
		wxT("Hyphenated, enclosed in parentheses"),
		wxT("Structured in integers")
	};
	int m_FormattingChoiceNChoices = sizeof( m_FormattingChoiceChoices ) / sizeof( wxString );
	m_FormattingChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_FormattingChoiceNChoices, m_FormattingChoiceChoices, 0 );
	m_FormattingChoice->SetSelection( 1 );
	horizontalSizer2->Add( m_FormattingChoice, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );

	verticalSizer->Add( horizontalSizer2, 1, wxALL|wxEXPAND, 5 );

	wxBoxSizer* horizontalSizer3 = new wxBoxSizer( wxHORIZONTAL );

	m_AllCaps = new wxCheckBox( this, wxID_ANY, wxT("Capitalize letters") );
	horizontalSizer3->Add( m_AllCaps, 1, wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );

	verticalSizer->Add( horizontalSizer3, 1, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5 );

	wxBoxSizer* horizontalSizerPreview = new wxBoxSizer( wxHORIZONTAL );

	GenerateUUID();

	m_UUIDPreview = new wxStaticText( this, wxID_ANY, m_currentUUID, wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE );
	m_UUIDPreview->Wrap( -1 );
	m_UUIDPreview->SetFont( wxFont( 8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL) );

	horizontalSizerPreview->Add( m_UUIDPreview, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND, 5 );

	verticalSizer->Add( horizontalSizerPreview, 1, wxALL|wxEXPAND, 5 );

	wxBoxSizer* horizontalSizer4;
	horizontalSizer4 = new wxBoxSizer( wxHORIZONTAL );

	m_btnGenerate = new wxButton( this, wxID_ANY, wxT("Generate"), wxDefaultPosition, wxDefaultSize, 0 );
	horizontalSizer4->Add( m_btnGenerate, 0, wxALL|wxEXPAND, 5 );

	m_btnCopy = new wxButton( this, wxID_ANY, wxT("Copy"), wxDefaultPosition, wxDefaultSize, 0 );
	horizontalSizer4->Add( m_btnCopy, 0, wxALL|wxEXPAND, 5 );

	m_btnClose = new wxButton( this, wxID_ANY, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0 );
	horizontalSizer4->Add( m_btnClose, 0, wxALL|wxEXPAND, 5 );

	verticalSizer->Add( horizontalSizer4, 1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5 );

	boxSizerAll->Add( verticalSizer, 1, wxEXPAND, 5 );

	SetSizer( boxSizerAll );
	Layout();
	Centre( wxBOTH );

	// Connect Events
	m_FormattingChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( UUIDDialog::OnFormatChanged ), NULL, this );
	m_AllCaps->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( UUIDDialog::OnAllCapsToggled ), NULL, this );
	m_btnGenerate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickGenerate ), NULL, this );
	m_btnCopy->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickCopy ), NULL, this );
	m_btnClose->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickClose ), NULL, this );
}

void UUIDDialog::GenerateUUID()
{
	using namespace boost::uuids;
	random_generator gen;

	m_uuid = gen();

	FormatUUID();
}

void UUIDDialog::FormatUUID()
{
	m_currentUUID = to_wstring(m_uuid).c_str();
	if(m_AllCaps->GetValue())
	{
		m_currentUUID.MakeUpper();
	}
	const int selectedFormat = m_FormattingChoice->GetSelection();
	wxString id1 = m_currentUUID.Mid(0,8);
	wxString id2 = m_currentUUID.Mid(9,4);
	wxString id3 = m_currentUUID.Mid(14,4);
	wxString id4 = m_currentUUID.Mid(19,4);
	wxString id5 = m_currentUUID.Mid(24);
	switch(selectedFormat)
	{
		case 0:
			{
				m_currentUUID = id1 + id2 + id3 + id4 + id5;
			}
		case 1:
		default:
			return;
		case 4:
			{
				m_currentUUID = wxT("{0x");
				m_currentUUID += id1 + wxT(",0x") + id2 + wxT(",0x") + id3;
				wxString lastBlock = id4 + id5;
				for(int i = 0; i < lastBlock.Len(); i += 2)
				{
					if(i == 0)
					{
						m_currentUUID += wxT(",{0x");
					}
					else
					{
						m_currentUUID += wxT(",0x");
					}
					m_currentUUID += lastBlock.Mid(i,2);
				}
				m_currentUUID += wxT("}}");
			}
			return;
		case 2:
			m_currentUUID = wxString(wxT("{")) + m_currentUUID + wxT("}");
			break;
		case 3:
			m_currentUUID = wxString(wxT("(")) + m_currentUUID + wxT(")");
			break;
	}
}

void UUIDDialog::UpdateUUID()
{
	m_UUIDPreview->SetLabel(m_currentUUID);
	Layout();
}

void UUIDDialog::OnFormatChanged(wxCommandEvent&)
{
	FormatUUID();
	UpdateUUID();
}

void UUIDDialog::OnAllCapsToggled(wxCommandEvent&)
{
	FormatUUID();
	UpdateUUID();
}

void UUIDDialog::OnClickGenerate(wxCommandEvent&)
{
	GenerateUUID();
	UpdateUUID();
}

void UUIDDialog::OnClickCopy(wxCommandEvent& event)
{
	if(wxTheClipboard->Open())
	{
		wxTheClipboard->SetData( new wxTextDataObject(m_currentUUID) );

		wxTheClipboard->Close();
	}
}

void UUIDDialog::OnClickClose(wxCommandEvent& /*event*/)
{
	EndModal(wxID_OK);
}

UUIDDialog::~UUIDDialog()
{
	// Disconnect Events
	m_FormattingChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( UUIDDialog::OnFormatChanged ), NULL, this );
	m_AllCaps->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( UUIDDialog::OnAllCapsToggled ), NULL, this );
	m_btnGenerate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickGenerate ), NULL, this );
	m_btnCopy->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickCopy ), NULL, this );
	m_btnClose->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( UUIDDialog::OnClickClose ), NULL, this );
}

